package webserver;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Contains get request from client
 */
public class HttpRequest {

    private static final String CONTENT_LENGTH = "Content-Length:";
    private static final String REQUESTED_PAGE = "requestedPage";
    private static final String SELECTED_VALUE = "on";

    private static Pattern PAGE_WITH_REQUEST = Pattern
	    .compile("(/([^\\?]*)(\\?(.*))?) HTTP/.*");

    private Map<String, String> map = new HashMap<String, String>();
    private List<String> paramsAsList = new ArrayList<String>();
    private Boolean postRequest;
    private int contentLength;

    private void parseLine(String request) {
	if (request == null)
	    return;
	if (request.contains("GET")) {
	    postRequest = false;
	    parseRequestLine(request);
	} else if (request.contains("POST")) {
	    postRequest = true;
	    parseRequestLine(request);
	} else if (request.contains(CONTENT_LENGTH)) {
	    this.contentLength = Integer.parseInt(request.replaceAll(
		    CONTENT_LENGTH, "").trim());
	}
    }

    public boolean isPostRequest() {
	if (postRequest == null) {
	    throw new RuntimeException("No request type defined");
	}
	return postRequest;
    }

    public int getContentLenght() {
	return contentLength;
    }

    private void parseRequestLine(String request) {
	Matcher matcher = PAGE_WITH_REQUEST.matcher(request);
	if (matcher.find()) {
	    String page = matcher.group(2);
	    if (page.trim().length() == 0) {
		map.put(HttpRequest.REQUESTED_PAGE, Consts.INDEX);
	    } else {
		map.put(HttpRequest.REQUESTED_PAGE, page);
	    }
	    parseParams(matcher.group(4));
	} else {
	    throw new RuntimeException("Request but didn't mached " + request);
	}
    }

    private void parseParams(String params) {
	try {
	    if (params != null && params.trim().length() != 0) {
		String[] keyValueString = params.split("&");
		for (String keyValue : keyValueString) {
		    String[] keyValueArray = keyValue.split("=");
		    if (keyValueArray.length > 1) {
			String name = URLDecoder.decode(keyValueArray[0],
				"UTF-8");
			String value = URLDecoder.decode(keyValueArray[1],
				"UTF-8");
			map.put(name.trim(), value.trim());
		    }
		}
	    }
	} catch (UnsupportedEncodingException e) {
	    e.printStackTrace();
	    throw new RuntimeException(e);
	}
    }

    public String getValueByName(String name) {
	return map.get(name);
    }

    public List<String> getSelectedParams() {
	List<String> res = new ArrayList<String>();
	for (Entry<String, String> ent : map.entrySet()) {
	    if (ent.getValue().equals(SELECTED_VALUE)) {
		res.add(ent.getKey());
	    }
	}
	return res;
    }

    public String getPage() {
	return map.get(REQUESTED_PAGE);
    }

    public String getSSID() {
	return map.get(Consts.PARAM_SSID);
    }

    @Override
    public String toString() {
	return "HttpRequest [Params=" + this.map + "]";
    }

    public void add(String s) {
	paramsAsList.add(s);
    }

    public void parse() {
	for (String str : paramsAsList) {
	    parseLine(str);
	}
    }

    public void parsePostParams(String params) {
	parseParams(params);
    }
}
